
/**
 *
 *
 *      opendu  Copyright (C) 2011  YouniS Ben Salah
 *
 *
 *      This file is part of opendu.
 *
 *      opendu is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      opendu is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with opendu.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *      Program                 ::      opendu
 *      Version                 ::      1.02, beta
 *      Date                    ::      July, August, September, October, November, 2011
 *
 *      Author                  ::      YouniS Ben Salah
 *      E-Mail                  ::      YouniS.BenSalah02@yahoo.de
 *      Website                 ::      http://myhttp.funpic.de
 *
 *      Module                  ::      Game
 *      C File                  ::      ygame.c
 *      Revision                ::      {}
 *
 *
 */




#include "yinclude.h"



/*
 *
 *
 *  Function                ::      initGame()
 *
 *  Constructor of Game structure.
 *
 *
 */

int initGame( Game *Imagame )
{
    int err_code = 0;

    Imagame->Word = NULL;
    Imagame->Word = malloc( sizeof(char)*STR_SIZE );
    if ( Imagame->Word == NULL ) {
        err_code = ERR_ALLOC;
    }
    *(Imagame->Word) = '\0';

    Imagame->End_of_game = 0;

    Imagame->List_of_used_letters = NULL;
    Imagame->List_of_used_letters = malloc( sizeof(char)*STR_SIZE );
    if ( Imagame->List_of_used_letters == NULL ) {
        err_code = ERR_ALLOC;
    }
    *(Imagame->List_of_used_letters) = '\0';

    Imagame->Hidden_word = NULL;
    Imagame->Hidden_word = malloc( sizeof(char)*STR_SIZE );
    if ( Imagame->Hidden_word == NULL ) {
        err_code = ERR_ALLOC;
    }
    *(Imagame->Hidden_word) = '\0';

    Imagame->Number_of_lifes = NUMBER_OF_LIFES;

    Imagame->Letter = '\0';

    Imagame->Name_player_1 = NULL;
    Imagame->Name_player_1 = malloc( sizeof(char)*STR_SIZE );
    if ( Imagame->Name_player_1 == NULL ) {
        err_code = ERR_ALLOC;
    }
    *(Imagame->Name_player_1) = '\0';

    Imagame->Name_player_2 = NULL;
    Imagame->Name_player_2 = malloc( sizeof(char)*STR_SIZE );
    if ( Imagame->Name_player_2 == NULL ) {
        err_code = ERR_ALLOC;
    }
    *(Imagame->Name_player_2) = '\0';

    return err_code;
}



/*
 *
 *
 *  Function                ::      dieinafireGame()
 *
 *  Destructor of Game structure.
 *
 *
 */

void dieinafireGame( Game *Imagame )
{
    free(Imagame->Word);
    free(Imagame->List_of_used_letters);
    free(Imagame->Hidden_word);
    free(Imagame->Name_player_1);
    free(Imagame->Name_player_2);
}



/*
 *
 *
 *  Function                ::      play()
 *
 *  It's the "core" function of the program. For now, only MP implemented.
 *
 *      0. start play_mp_mode;
 *      1. declare and initialize a new Game;
 *      2. clear screen;
 *      3. read names;
 *      4. read word from player1 and store it in Game->Word;
 *      5. while ( !End_of_game ) do
 *          5.0. clear screen;
 *          5.1. draw interface;
 *          5.2. read letter from player2 and store it in Game->Letter;
 *          5.3. if ( !(letter in word) ) then
 *              5.3.0. decrease Number_of_lifes by 1;
 *          endif
 *          5.4. update stuff;
 *      endwhile
 *      6. endGame;
 *      7. return replay again (?)
 *      8. end play_mp_mode;
 *
 *
 */

int play( int mode )
{
    /* warning: unused parameter ‘mode’
     * i know ): only multiplayer implemented.
     */

    Game Imagame;
    int letter_found = 0;
    char *imaword = NULL;
    int err_code = 0;
    err_code = initGame(&Imagame);  /* initialize Game */
    if ( err_code ) {
        exit(err_code);
    }

    clearScreen();

    readNames(&Imagame);

    readWord(&Imagame);

    while( getchar() != '\n');

    while ( !(Imagame.End_of_game) ) {
        clearScreen();
        drawScreen(&Imagame, COLS, MARGIN);                /* INTERFACE !!!!!!!! */
        readLetter(&Imagame);

            /*  search for letter in word  */
        letter_found = 0;
        for ( imaword=Imagame.Word; *imaword; imaword++ ){
            if ( *imaword == Imagame.Letter ) {
                letter_found = 1;
            }
        }
        if ( !letter_found ) {
            Imagame.Number_of_lifes--;
        }

        refreshHidden_word(&Imagame);
        refreshEnd_of_game(&Imagame);
    }

    endGame(&Imagame);

    dieinafireGame( &Imagame );     /* destroy Game */

    return askAgain();
}



/*
 *
 *
 *  Function                ::      endGame()
 *
 *  Writes some messages at the end.
 *
 *
 */

void endGame( Game *Imagame )
{
    char *winner = NULL;
    winner = malloc( sizeof(char)*STR_SIZE );
    if ( winner == NULL ) {
        exit(ERR_ALLOC);
    }

    clearScreen();

    drawBorder( COLS );
    drawEmptyLine( COLS );
    drawEmptyLine( COLS );

    drawHangman( Imagame );
    drawEmptyLine( COLS );
    if ( Imagame->End_of_game == 1 ) {
        sprintf( winner, "%s wins (: !!", Imagame->Name_player_1);
    }
    else {
        sprintf( winner, "%s wins (: !!", Imagame->Name_player_2);
    }
    drawNFromLeft( winner, COLS, MARGIN );
    drawEmptyLine( COLS );
    drawNFromLeft( Imagame->Word, COLS, 2*MARGIN );

    drawEmptyLine( COLS );
    drawEmptyLine( COLS );
    drawBorder( COLS );
}



/*
 *
 *
 *  Function                ::      readNames()
 *
 *  Reads the names of the players and stores the results in
 *  Game->Name_player_1
 *  Game->Name_player_2
 *
 *
 */

void readNames( Game *Imagame )
{
    printf("\n[player 1] :: enter name");
    write(PROMPT);
    scanf("%s", Imagame->Name_player_1);

    printf("\n[player 2] :: enter name");
    write(PROMPT);
    scanf("%s", Imagame->Name_player_2);
}



/*
 *
 *
 *  Function                ::      readLetter()
 *
 *
 *  Reads a letter from player 2 and stores the result in
 *  Game->Letter
 *
 *
 */

void readLetter( Game *Imagame )
{
    char *s = NULL;
    int valid = 0;

    do {
        printf("\n[%s] :: enter letter", Imagame->Name_player_2);
        write(PROMPT);

        Imagame->Letter = readCh();

            /*  changes the Imagame->Letter to UPPERCASE */
        Imagame->Letter = toupper( Imagame->Letter );

        if ( letterAlreadyUsed(Imagame) ) {
            printf("%c? you already entered this letter o.O\n", Imagame->Letter);
        }
        else {
            valid = 1;
        }
    } while ( !valid );

        /*  add letter to the list of used letters */
    for ( s=Imagame->List_of_used_letters; *s; s++ );
    *s = Imagame->Letter;
    *(s+1) = '\0';
}



/*
 *
 *
 *  Function :: askAgain()
 *
 *  It returns whether or not the user wants to play again.
 *      1 -> to play again
 *      2 -> to return to menu
 *
 *
 */

char askAgain()
{
    char again = '\0';
    while ( again != '1' && again != '2' ) {
        printf("\n\nplay again ?\n\n[1 ][ yes]\n[2 ][ no]");
        write(PROMPT);

        again = readCh();
    }

    return again;
}



/*
 *
 *
 *  Function                ::      refreshEnd_of_game()
 *
 *  Refresh the value of Game->End_of_game
 *
 *
 */

void refreshEnd_of_game( Game *Imagame )
{
    if ( !(Imagame->Number_of_lifes) ) {
        Imagame->End_of_game = 1;
    }
    else {
        int found = 0;
        char *s;
        for ( s=Imagame->Hidden_word; *s && !found; s++ ) {
            if ( *s == '-' ) {
                found = 1;
            }
        }
        Imagame->End_of_game = 2-found*2;
    }
}



/*
 *
 *
 *  Function                ::      refreshHidden_word()
 *
 *  Refresh the value of Game->Hidden_word
 *
 *
 */

void refreshHidden_word( Game *Imagame )
{
    int i;
    char *s;
    int found = 0;
    for ( i=0; *((Imagame->Word)+i); i++ ) {
        for ( s=Imagame->List_of_used_letters; *s && !found; s++ ) {
            if ( *s == *((Imagame->Word)+i) ) {
                found = 1;
            }
        }
        if ( found ) {
            *((Imagame->Hidden_word)+i) = *((Imagame->Word)+i);
        }
        else {
            *((Imagame->Hidden_word)+i) = '-';
        }
        found = 0;
    }
}



/*
 *
 *
 *  Function                ::      readWord()
 *
 *  The function readWord() reads a string from player 1, rejects it until its length is < 16.
 *  The result will be transformed into UPPERCASE and stored in Word object.
 *  Game->Hidden_word will be refreshed.
 *
 *
 */

void readWord( Game *Imagame )
{
    int valid = 0;
    char *s = NULL, *p = NULL;

    while ( !valid ) {
        printf("\n[%s] :: enter word", Imagame->Name_player_1);
        write(PROMPT);
        scanf("%s", Imagame->Word);
        if ( strlen(Imagame->Word) < 16 ) {
            valid = 1;
        }
        else {
            printf("word too long ._.\n");
        }
    }

    for ( s=Imagame->Word, p=Imagame->Hidden_word; *s; s++, p++ ) {
        *s = toupper(*s);
        *p = '-';
    }
    *p = '\0';
}



/*
 *
 *
 *  Function                ::      letterInWord()
 *
 *  Tests if Game->Letter is already used to prevent user from repeating a letter.
 *
 *
 */

int letterAlreadyUsed( Game *Imagame )
{
    int found = 0;
    char *word = Imagame->List_of_used_letters;

    while ( !found && *word ) {
        if ( *word == Imagame->Letter ) {
            found = 1;  /* letter exists ! */
        }
        else {
            word++;     /* continue searching ... */
        }
    }
    return found;
}




